package com.zhiyou100.interceptor;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;

import com.zhiyou100.util.RedisUtil;

public class RedisInterceptor implements MethodInterceptor{
	Logger logger = Logger.getLogger(RedisInterceptor.class);
	private List<String> targetNames;
	private List<String> methodNames ;
	private RedisUtil redisUtil;
	public void setRedisUtil(RedisUtil redisUtil) {
		this.redisUtil = redisUtil;
	}

	public RedisInterceptor(){
		try {
			//通过初始化方法，知道不需要加入缓存的类和方法有哪些
			File file = new File("C:\\Users\\Administrator\\Desktop\\11.16-30\\11-30\\maven_ssm\\src\\main\\resources\\redis.properties");
			InputStream is = new FileInputStream(file);
			Properties p = new Properties();
			p.load(is);

			//获取不需要加入缓存的类和方法
			String[] targets=p.getProperty("targetNames").split(",");
			String[] methods = p.getProperty("methodNames").split(",");

			//把数组转换为集合
			targetNames = new ArrayList<>();
			methodNames = new ArrayList<>();

			for (String target : targets) {
				targetNames.add(target);
			}
			for (String method : methods) {
				methodNames.add(method);
			}


		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("redis的配置文件找不到");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("读取redis配置文件失败");
		}
	}

	//是否加入缓存,需要返回true，不需要返回false
	private boolean isCache(String targetName,String methodName){
		if(targetNames.contains(targetName)||methodNames.contains(methodName)){
			return false;
		}
		return true;
	}
	
	//设置缓存的键
	public String getCacheKey(String targetName,String methodName,Object[] args){
		//类名_方法名_参数名_
		StringBuilder sbd = new StringBuilder(targetName+"_"+methodName);
		for (Object arg : args) {
			sbd.append("_").append(arg);
		}
		return sbd.toString();
	}

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		//获取类名
		String target=invocation.getThis().getClass().getName();
		//获取方法名
		String method = invocation.getMethod().getName();
		
		if(method.startsWith("insert")||method.startsWith("update")||method.startsWith("delete")){
			//清除缓存
			redisUtil.flushCache();
			return invocation.proceed();//直接执行方法
		}
		
		//判断是否需要加入缓存
		if(!isCache(target, method)){
			return invocation.proceed();
		}
		//获取参数
		Object[] args=invocation.getArguments();
		String key = getCacheKey(target, method, args);
		//如果缓存中有，就不需要放入缓存了
		if(redisUtil.exists(key)){
			return redisUtil.get(key);
		}
		Object value=invocation.proceed();//执行查询的方法得到的结果
		if(value==null){
			return value;
		}
		
		//加入线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				//如果不是null值，需要放入缓存
				redisUtil.set(key, value);
			}
		}).start();
		
		return value;
	}

}
